home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 008 / 68kgraph.arc / BITPRIM.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-12-13  |  12.0 KB  |  351 lines

  1. ******************************************************************
  2. * COPYRIGHT (C) 1986 by Donald Krantz and James Stanley
  3. * - Note: This is a real, live, actual, registered copyright,
  4. *   and should be treated as such. This source code is from
  5. *   the book "68000 Assembly Language", Krantz and Stanley,
  6. *   Addison-Wesley Publishing Company, Reading, MA, 1986.
  7. *   Permission granted by the authors for non-commercial use
  8. *   in programs released to the public domain, as long as this
  9. *   copyright notice remains attached and visible.
  10. *
  11. *****************************************************************
  12. * BITPRIM - bit mapped graphics primitives
  13. #bit.h
  14.  
  15.     xref    image,sqrt
  16.     xdef    g_pix,g_mode,g_vector,g_circle,g_clear,g_fill
  17.     xdef    mode
  18.  
  19. *****************************************************************
  20. * SET_PIX - sets the pixel where D0.W = X and D1.W = Y
  21. g_pix:
  22.     movem.l    d0/d1/a0,-(a7)    * save caller's registers
  23. *
  24.     cmp.w    #hor_b,d0    * check clipping horizontal
  25.     bcc    sk0_sp        * exit on over X
  26.     cmp.w    #vert,d1    * check clipping vertical
  27.     bcc    sk0_sp        * exit on over Y
  28. *
  29.     move.l    #image,a0    * get base of image area
  30.     mulu    #(hor_w*2),d1    * get vertical offset to line
  31.     add.l    d1,a0        * and add to base address
  32.     move.w    d0,d1        * save X for later
  33.     lsr.w    #3,d0        * get number of bytes to pixel 
  34.     add.w    d0,a0        * add to pointer
  35.     and.w    #$0007,d1    * strip all but bit number
  36.     move.w    mode,d0        * get mode flag
  37.     lsr.w    #1,d0        * pop bit 0 into carry flag
  38.     bcs    sk1_sp        * jam mode jump
  39.     lsr.w    #1,d0        * pop bit 1 into carry flag
  40.     bcs    sk2_sp        * complement mode jump
  41.     lsr.w    #1,d0        * pop bit 2 into carry flag
  42.     bcs    sk3_sp        * set mode jump
  43.     bclr    d1,(a0)        * falls thru to clear mode
  44.     bra    sk0_sp        * so we're done
  45. sk1_sp:
  46. sk3_sp:
  47.     bset    d1,(a0)        * jam and set are the same here        
  48.     bra    sk0_sp        * now we're done
  49. sk2_sp:
  50.     bchg    d1,(a0)        * complement mode
  51. sk0_sp:
  52.     movem.l    (a7)+,d0/d1/a0    * restore caller's registers
  53.     rts
  54. *****************************************************************
  55. * SET_MODE - Sets mode to value contained in D0.W
  56. g_mode:
  57.     move.w    d0,mode
  58.     rts
  59. *****************************************************************
  60. * G_VECTOR - draws a vector from (D0.W,D1.W) to (D2.W,D3.W)
  61. g_vector:
  62.     movem.l    d0-d7,-(a7)    * Save registers
  63. ******* Scale and save vector origin coordinates ****************
  64.     move.w    d0,d4        * setup base for X
  65.     swap    d4        * scale x 2^16
  66.     clr.w    d4        * make even number
  67.     move.w    d1,d5        * setup base for Y
  68.     swap    d5        * scale x 2^16
  69.     clr.w    d5        * make even number
  70. ******* Determine absolute and signed run in X ******************
  71.     sub.w    d0,d2        * find difference in X
  72.     move.w    d2,d0        * save signed difference
  73.     bpl    sk1_vec        * skip X absolute value convert
  74.     neg.w    d0        * D0 is X absolute distance
  75. ******* Determine absolute and signed run in Y ******************
  76. sk1_vec:
  77.     sub.w    d1,d3        * find difference in Y
  78.     move.w    d3,d1        * save signed difference
  79.     bpl    sk2_vec        * skip Y absolute value convert
  80.     neg.w    d1        * D1 is Y absolute distance
  81. ******* Determine independent (larger) and dependent axis *******
  82. sk2_vec:
  83.     cmp.w    d0,d1        * see if X dif > Y dif
  84.     bgt    Y_bigger    * jump if y is bigger
  85. ******* X is independent axis - determine X step as +/- 1.0 *****
  86.     tst.w    d2        * check sign of X run
  87.     bmi    sk3_vec        * jump if negative
  88.     move.l    #$00010000,d6    * setup X step = 1.0
  89.     bra    sk4_vec        * jump to Y setup
  90. sk3_vec:
  91.     move.l    #$FFFF0000,d6    * setup Y step = -1.0
  92. ******* Determine Y step as scaled fixed point longword *********
  93. sk4_vec:
  94.     swap    d3        * Scale up 
  95.     clr.w    d3        * make longword
  96.     asr.l    #2,d3        * take out two bits of precision
  97.     divs    d0,d3        * divide by independent axis
  98.     ext.l    d3        * make long again
  99.     asl.l    #2,d3        * put two precisions bits back
  100.     move.l    d3,d7        * D7 is signed Y step
  101.     move.w    d0,d2        * get independant axis counter
  102.     bra    sk7_vec        * go do output
  103. ******* Y is independent axis - setup Y step as +/- 1.0 *********
  104. Y_bigger:
  105.     tst.w    d3        * check sign of Y run
  106.     bmi    sk5_vec        * jump if step negative
  107.     move.l    #$00010000,d7    * make Y step 1.0
  108.     bra    sk6_vec        * jump to X setup
  109. sk5_vec:
  110.     move.l    #$FFFF0000,d7    * make Y step -1.0
  111. ******* Determine X step as scaled fixed point longword *********
  112. sk6_vec:
  113.     swap    d2        * Scale up 
  114.     clr.w    d2        * make longword
  115.     asr.l    #2,d2        * Take out two bits of precision
  116.     divs    d1,d2        * divide by independent axis
  117.     ext.l    d2        * make long again
  118.     asl.l    #2,d2        * put back the precision
  119.     move.l    d2,d6        * D6 is signed X step
  120.     move.w    d1,d2        * get independant axis counter
  121. *
  122. ******* Pixel output loop ***************************************
  123. sk7_vec:
  124.     bra    sk8_vec        * do loop test before body
  125. lp0_vec:
  126.     move.l    d4,d0        * get scaled X position
  127.     add.l    #$00008000,d0    * round up by adding 0.5
  128.     swap    d0        * scale X down for output
  129.     move.l    d5,d1        * get scaled Y position
  130.     add.l    #$00008000,d1    * round up by adding 0.5
  131.     swap    d1        * scale Y down for output
  132.     bsr    g_pix        * put the pixel
  133.     add.l    d6,d4        * add X step
  134.     add.l    d7,d5        * add Y step
  135. sk8_vec:
  136.     dbra    d2,lp0_vec    * loop around
  137.     movem.l    (a7)+,d0-d7    * restore registers
  138.     rts
  139. *****************************************************************
  140. * Draws a circle around (D0.W,D1.W) of radius D2.W
  141. g_circle:
  142.     movem.l    d0-d7,-(a7)    * Save registers
  143.     move.w    d0,d6        * d6 will be X base pixel
  144.     move.w    d1,d7        * d7 will be Y base pixel
  145.     move.w    d2,d3        * get copy of radius
  146.     mulu    d3,d3        * d3.l is radius squared
  147.     swap    d2        * make into scaled longword
  148.     clr.w    d2        * truncate  
  149.     divu    #$B504,d2    * radius / (sqr(2) << 15)
  150.     add.w    #1,d2        * round up
  151.     asr.l    #1,d2        * align D2 because sqr(2) scaled  
  152. lp0_cir:
  153.     move.w    d2,d4        * d4 is a scratch register
  154.     mulu    d4,d4        * d4 is (rise**2)
  155.     move.l    d3,d0        * d0 is  scratch register
  156.     sub.l    d4,d0        * d0 is (run**2) 
  157.     bsr    sqrt        * after call, d0 = (run)
  158.     move.w    d0,d4        * save run
  159. ******* Quadrant I, counterclockwise
  160.     move.w    d6,d0        * X center
  161.     move.w    d7,d1        * Y center
  162.     add.w    d4,d0        * add run
  163.     add.w    d2,d1        * add rise
  164.     bsr    g_pix
  165. ******* Quadrant I, clockwise
  166.     move.w    d6,d0        * X center
  167.     move.w    d7,d1        * Y center
  168.     add.w    d4,d1        * add rise
  169.     add.w    d2,d0        * add run
  170.     bsr    g_pix
  171. ******* Quadrant II, counterclockwise
  172.     move.w    d6,d0        * X center
  173.     move.w    d7,d1        * Y center
  174.     sub.w    d2,d0        * add rise
  175.     add.w    d4,d1        * add run
  176.     bsr    g_pix
  177. ******* Quadrant II, clockwise
  178.     move.w    d6,d0        * X center
  179.     move.w    d7,d1        * Y center
  180.     add.w    d2,d1        * add rise
  181.     sub.w    d4,d0        * add run
  182.     bsr    g_pix
  183. ******* Quadrant III, counterclockwise
  184.     move.w    d6,d0        * X center
  185.     move.w    d7,d1        * Y center
  186.     sub.w    d2,d1        * add rise
  187.     sub.w    d4,d0        * add run
  188.     bsr    g_pix
  189. ******* Quadrant III, clockwise
  190.     move.w    d6,d0        * X center
  191.     move.w    d7,d1        * Y center
  192.     sub.w    d2,d0        * add rise
  193.     sub.w    d4,d1        * add run
  194.     bsr    g_pix
  195. ******* Quadrant IV, counterclockwise
  196.     move.w    d6,d0        * X center
  197.     move.w    d7,d1        * Y center
  198.     add.w    d2,d0        * add rise
  199.     sub.w    d4,d1        * add run
  200.     bsr    g_pix
  201. ******* Quadrant IV, clockwise
  202.     move.w    d6,d0        * X center
  203.     move.w    d7,d1        * Y center
  204.     add.w    d4,d0        * add run
  205.     sub.w    d2,d1        * add rise
  206.     bsr    g_pix
  207.     dbra    d2,lp0_cir    * loop for next set 
  208.     movem.l    (a7)+,d0-d7    * Restore registers
  209.     rts
  210. *****************************************************************
  211. * Clears the graphics image area
  212. g_clear:
  213.     movem.l    a0/d0,-(a7)    * save registers
  214.     move.l    #image,a0    * Get image area base address
  215.     move.l    #(vert*hor_w/2),d0
  216. lp0_cl:
  217.     clr.l    (a0)+        * zero out byte
  218.     subq.l    #1,d0        * pop counter
  219.     bne    lp0_cl        * loop for next
  220.     movem.l    (a7)+,a0/d0    * restore registers
  221.     rts
  222. *****************************************************************
  223. * Fills the area bounded by (D0.W,D1.W) and (D2.W,D3.W)
  224. g_fill:
  225.     movem.l    d0-d7/a0/a1,-(a7) save callers registers
  226. ******* Adjust so that D2.W >= D0.W and D3.W >= D1.W
  227.     cmp.w    d0,d2        * Who's bigger?
  228.     bge    sk1_fil        * jump if d2 is bigger
  229.     exg    d0,d2        * swap if not
  230. sk1_fil:
  231.     cmp.w    d1,d3        * Who's bigger here?
  232.     bge    sk2_fil        * jump if d3 is bigger
  233.     exg    d1,d3        * swap if not
  234. sk2_fil:
  235. ******* Calculate (number of rows) - 1, save in D7
  236.     move.w    d3,d7        * uses D7 as accumulator
  237.     sub.w    d1,d7        * D7 is (#rows-1)
  238. ******* Calculate first byte address in A0
  239.     move.l    #image,a0    * A0 is base of image memory     
  240.     mulu    #(hor_w*2),d1    * D1 is row offset from zero
  241.     move.w    d0,d3        * D3 is a scratch register
  242.     asr.w    #3,d3        * D3 is number of bytes into row
  243.     add.w    d3,d1        * D1 is bytes into image
  244.     add.w    d1,a0        * A0 is now address of first byte
  245. ******* Make mask for left fragment in D4.B
  246.     move.w    d0,d1        * D1 is scratch register
  247.     and.w    #$0007,d1    * D1 is pixel address
  248.     move.w    #$00FF,d4    * D4 will be fragment mask
  249.     lsl.b    d1,d4        * move mask to correct pixels
  250. ******* Make mask for right fragment in D6.B
  251.     move.w    d2,d1        * D1 is scratch register
  252.     and.w    #$07,d1        * D1 is pixel address
  253.     move.w    #$FE01,d6    * D6 will be fragment mask
  254.     rol.w    d1,d6        * move mask to correct pixels
  255. ******* Compute distance 'twixt start and end byte in row 
  256.     lsr.w    #3,d0        * get starting offset into row
  257.     lsr.w    #3,d2        * get ending offset into row
  258. ******* Test for special case - left and right frags in same byte
  259.     sub.w    d0,d2        * are they the same?
  260.     bne    sk3_fil        * jump if not...
  261. ******* process start/end in same byte
  262.     and.b    d6,d4        * combine the two masks
  263.     btst    #0,mode+1    * look for jam mode
  264.     bne    sk4_fil        * go jam
  265.     btst    #1,mode+1    * look for complement mode
  266.     bne    sk5_fil        * go complement
  267.     btst    #2,mode+1    * look for set mode
  268.     bne    sk4_fil        * it's the same as jam here
  269. ******* must be clear mode, special case. Let's do it! (yay!) ***
  270.     not.b    d4        * invert the mask
  271. lp1_fil:
  272.     and.b    d4,(a0)        * reset the right bits
  273.     add.l    #(hor_w*2),a0    * move the address to next row
  274.     dbra    d7,lp1_fil    * and repeat as necessary
  275.     bra    ex_fill        * finished!
  276. ******* jam or set mode, special case ***************************
  277. sk4_fil:
  278.     or.b    d4,(a0)        * set the right bits
  279.     add.l    #(hor_w*2),a0    * move the address to next row
  280.     dbra    d7,sk4_fil    * and repeat
  281.     bra    ex_fill        * exit
  282. ******* complement mode, special case ***************************
  283. sk5_fil:
  284.     eor.b    d4,(a0)        * complement the right bits
  285.     add.l    #(hor_w*2),a0    * move the address to next row
  286.     dbra    d7,sk4_fil    * repeat
  287.     bra    ex_fill        * exit
  288. ******* normal (multi-byte/row) fill case continued *************
  289. sk3_fil:
  290.     subq.w    #1,d2        * d2 is now number of whole bytes
  291.     btst    #0,mode+1    * look for jam mode
  292.     bne    sk6_fil        * go jam
  293.     btst    #1,mode+1    * look for complement mode
  294.     bne    sk7_fil        * go complement
  295.     btst    #2,mode+1    * look for set mode
  296.     bne    sk6_fil        * it's the same as jam here
  297. ******* Must be clear mode, normal case *************************
  298.     not.b    d4        * invert start mask
  299.     not.b    d6        * invert end mask
  300. lp2_fil:
  301.     move.w    d2,d5        * Have to save d2 
  302.     move.l    a0,a1        * A1 can be modified, A0 can't.
  303.     and.b    d4,(a1)+    * catch left-hand bits
  304.     bra    sk8_fil        * do loop test before body
  305. lp3_fil:
  306.     clr.b    (a1)+        * zero out middle bytes     
  307. sk8_fil:
  308.     dbra    d5,lp3_fil    * repeat for middle bytes
  309.     and.b    d6,(a1)        * get right-hand bits
  310.     add.l    #(hor_w*2),a0    * move to next row
  311.     dbra    d7,lp2_fil    * repeat for all rows
  312.     bra    ex_fill        * and quit
  313. ******* Jam or Set mode, normal case ****************************
  314. sk6_fil:
  315.     move.w    d2,d5        * Have to save d2 
  316.     move.l    a0,a1        * A1 can be modified, A0 can't.
  317.     or.b    d4,(a1)+    * catch left-hand bits
  318.     bra    sk9_fil        * do loop test before body
  319. lp4_fil:
  320.     move.b    #$FF,(a1)+    * set middle bytes     
  321. sk9_fil:
  322.     dbra    d5,lp4_fil    * repeat for middle bytes
  323.     or.b    d6,(a1)        * get right-hand bits
  324.     add.l    #(hor_w*2),a0    * move to next row
  325.     dbra    d7,sk6_fil    * repeat for all rows
  326.     bra    ex_fill        * and quit
  327. ******* Complement mode, normal case ****************************
  328. sk7_fil:
  329.     move.w    d2,d5        * Have to save d2 
  330.     move.l    a0,a1        * A1 can be modified, A0 can't.
  331.     eor.b    d4,(a1)+    * catch left-hand bits
  332.     bra    sk10_fil    * do loop test before body
  333. lp5_fil:
  334.     eor.b    #$FF,(a1)+    * zero out middle bytes     
  335. sk10_fil:
  336.     dbra    d5,lp5_fil    * repeat for middle bytes
  337.     eor.b    d6,(a1)        * get right-hand bits
  338.     add.l    #(hor_w*2),a0    * move to next row
  339.     dbra    d7,sk7_fil    * repeat for all rows
  340. ******* fill procedure common exit ******************************
  341. ex_fill:
  342.     movem.l    (a7)+,d0-d7/a0/a1 restore registers
  343.     rts
  344. *****************************************************************
  345.  
  346.     data
  347. mode    dc.w    jam_m        * start in jam mode
  348.  
  349.     end
  350.